package module.auth.impl;

import common.model.Entity.User;
import common.model.Entity.VerificationCodeCache;
import dao.UserDao;
import dao.impl.UserDaoImpl;
import module.auth.UserService;
import network.protocol.Response;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import network.server.ClientHandler;
import network.server.session.SessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 用户服务实现类
 * <p>
 * 提供用户注册、登录、修改密码、邮箱验证码相关功能。
 * 单例模式，通过 {@link #getInstance()} 获取实例。
 */
public class UserServiceImpl implements UserService {

    private final UserDao userDao = new UserDaoImpl();
    private static final UserService INSTANCE = new UserServiceImpl();
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    /**
     * 获取单例实例
     *
     * @return UserServiceImpl 实例
     */
    public static UserService getInstance() {
        return INSTANCE;
    }

    /**
     * 用户注册
     *
     * @param username 用户名
     * @param password 密码
     * @param role     用户角色
     * @param email    邮箱
     * @param phone    手机号
     * @param realName 真实姓名
     * @param gender   性别
     * @param avatar   头像地址
     * @return 注册结果
     */
    @Override
    public Response<?> doRegister(String username, String password, Integer role, String email,
                                  String phone, String realName, Boolean gender, String avatar) {
        try {
            if (username == null || username.trim().isEmpty()) return Response.error("用户名不能为空");
            if (email == null || !email.matches("^[\\w-.]+@([\\w-]+\\.)+[\\w-]{2,4}$")) return Response.error("邮箱格式不合法");
            if (userDao.existsByUsername(username)) return Response.error("用户名已存在");
            if (userDao.existsByEmail(email)) return Response.error("邮箱已存在");

            User newUser = new User();
            newUser.setUsername(username);
            newUser.setPassword(password);
            newUser.setEmail(email);
            newUser.setRole(role);
            newUser.setStatus(1);
            newUser.setPhone(phone);
            newUser.setRealName(realName);
            newUser.setGender(gender);
            newUser.setAvatar(avatar);

            if (!userDao.save(newUser)) return Response.error("注册失败，请稍后重试");
            return Response.success();
        } catch (Exception e) {
            return Response.error("服务器内部错误: " + e.getMessage());
        }
    }

    /**
     * 用户登录
     *
     * @param sessionId 当前客户端 sessionId
     * @param username  用户名
     * @param password  密码
     * @return 登录结果，包括绑定后的 sessionId 和用户信息
     */
    @Override
    public Response<?> doLogin(String sessionId, String username, String password) {
        try {
            if (username == null || username.trim().isEmpty()) return Response.error("用户名不能为空");
            if (password == null || password.trim().isEmpty()) return Response.error("密码不能为空");

            User user = userDao.findByUsername(username).get();
            if (user == null) return Response.error("用户不存在");
            if (!user.getPassword().equals(password)) return Response.error("密码错误");
            if (user.getIsDeleted() != null && user.getIsDeleted() == 1) return Response.error("用户已被删除");

            try {
                InetAddress localHost = InetAddress.getLocalHost();
                String ip = localHost.getHostAddress();
                userDao.updateLoginInfo(user.getId(), ip);
            } catch (UnknownHostException e) {
                logger.error("获取本地IP地址失败", e);
            }

            ClientHandler clientHandler = SessionManager.getSession(sessionId);
            String newSessionId = clientHandler.bindUser(user);

            Map<String, Object> resMap = new HashMap<>();
            resMap.put("data", user);
            resMap.put("sessionId", newSessionId);

            logger.info(resMap.toString());
            return Response.success(resMap);

        } catch (Exception e) {
            return Response.error("服务器内部错误: " + e.getMessage());
        }
    }

    /**
     * 修改密码（需提供原密码）
     *
     * @param username  用户名
     * @param origin_pw 原密码
     * @param new_pw    新密码
     * @return 修改结果
     */
    @Override
    public Response<?> doChangePassword(String username, String origin_pw, String new_pw) {
        if (username == null || username.trim().isEmpty()) return Response.error("用户名不能为空");
        if (origin_pw == null || origin_pw.trim().isEmpty()) return Response.error("原密码不能为空");
        if (new_pw == null || new_pw.trim().isEmpty()) return Response.error("新密码不能为空");

        User user = userDao.findByUsername(username).get();
        if (user == null) return Response.error("用户不存在");
        if (!user.getPassword().equals(origin_pw)) return Response.error("原密码错误");
        if (!userDao.updatePassword(user.getId(), new_pw)) return Response.error("修改密码失败，请稍后重试");
        return Response.success();
    }

    /**
     * 发送邮箱验证码
     *
     * @param email 用户邮箱
     * @return 返回邮箱与生成的验证码
     */
    @Override
    public Response<?> SendEmail(String email) {
        if (email == null || !email.matches("^[\\w-.]+@([\\w-]+\\.)+[\\w-]{2,4}$")) return Response.error("邮箱格式不合法");

        User user = userDao.findByEmail(email).get();
        if (user == null) return Response.error("用户不存在");

        String generatedPassword = UUID.randomUUID().toString().substring(0, 8);
        VerificationCodeCache.storeCode(email, generatedPassword);

        ArrayList<String> res = new ArrayList<>();
        res.add(email);
        res.add(generatedPassword);
        return Response.success(res);
    }

    /**
     * 使用邮箱验证码修改密码
     *
     * @param email 用户邮箱
     * @param pw    新密码
     * @return 修改结果
     */
    @Override
    public Response<?> ChangePassword(String email, String pw) {
        User user = userDao.findByEmail(email).get();
        if (!userDao.updatePassword(user.getId(), pw)) return Response.error("修改密码失败，请稍后重试");
        return Response.success();
    }

    /**
     * 验证密码是否匹配
     *
     * @param pw      用户输入密码
     * @param send_pw 系统发送的验证码
     * @return 验证结果
     */
    @Override
    public Response<?> CheckPassword(String pw, String send_pw) {
        if (pw.equals(send_pw)) return Response.success();
        return Response.error("验证失败");
    }
}
